package net.jcip.chapter2;

import java.io.IOException;
import java.math.BigInteger;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.*;
import javax.servlet.*;
import javax.sound.midi.Soundbank;

import net.jcip.annotations.*;

/**
 * CountingFactorizer
 * <p>
 * Servlet that counts requests using AtomicLong
 *
 * @author Brian Goetz and Tim Peierls
 */
@ThreadSafe
public class CountingFactorizer extends GenericServlet implements Servlet {


    /**
     * 从 CPU 指令保证  原子执行;
     */
    private final AtomicLong count = new AtomicLong(0);

    public long getCount() { return count.get(); }

    public void service(ServletRequest req, ServletResponse resp) {
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = factor(i);
        count.incrementAndGet();

        System.out.println("INFO " + Thread.currentThread().getName() + " count ==> " + count);

        encodeIntoResponse(resp, factors);
    }

    private void encodeIntoResponse(ServletResponse res, BigInteger[] factors) {}

    private BigInteger extractFromRequest(ServletRequest req) {
        return new BigInteger("1");
    }

    private BigInteger[] factor(BigInteger i) { return null; }



    /**
     * 验证
     *
     * */
    public static void main(String[] args) throws  Exception {


        ExecutorService executorService = Executors.newFixedThreadPool(100); /*在这里已经创建线程对象了*/

        CountDownLatch countDownLatch = new CountDownLatch(1000);

        Class<?> clazz = Class.forName("net.jcip.chapter2.CountingFactorizer");
        CountingFactorizer servlet = (CountingFactorizer) clazz.newInstance();
        for (int i = 0; i < 1000; i++) {
            /*execute 中的是任务代码, 而不是线程对象 */
            executorService.execute(() -> {

                servlet.service(null, null);
                countDownLatch.countDown();

            });
        }

        System.out.println( "WARN  " + Thread.currentThread().getName() + "  卡住");
        countDownLatch.await(1000, TimeUnit.SECONDS);
        executorService.shutdown();
        System.out.println("servlet.getCount() = " + servlet.getCount());
    }


}
